package top.gytf.unifiedcall.producer.response;

import org.springframework.lang.Nullable;
import top.gytf.unifiedcall.common.api.ApiDefinition;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;

/**
 * 响应处理上下文信息
 */
public interface ResponseHandlerContext {
    /**
     * 获取响应基本信息
     */
    ApiDefinition getApiDefinition();

    /**
     * 添加参数
     *
     * @param name  参数名称
     * @param value 参数对象
     *
     * @throws IllegalArgumentException 参数名称已存在
     */
    void addParameter(String name, Object value);

    /**
     * 设置参数，如果存在会替换
     *
     * @param name  参数名称
     * @param value 参数对象
     */
    void setParameter(String name, Object value);

    /**
     * 移除参数
     *
     * @param name 参数名称
     */
    void removeParameter(String name);

    /**
     * 获取所有参数，Key为参数名称，Value为参数对象
     */
    Map<String, Object> getParameterMap();

    /**
     * 根据名称获取指定参数
     *
     * @param name 参数名称
     *
     * @return 参数对象，如果不存在则返回 {@code Optional.empty()}
     */
    Optional<Object> getParameterOpt(String name);

    /**
     * 根据名称获取指定参数
     *
     * @param name 参数名称
     *
     * @return 参数对象，如果不存在则返回 {@code null}
     */
    @Nullable
    default Object getParameter(String name) {
        return getParameterOpt(name).orElse(null);
    }

    /**
     * 根据名称获取指定参数，不存在则创建并放入
     *
     * @param name                   参数名称
     * @param supplier               如果不存在则创建的函数
     *
     * @return 参数对象
     */
    default Object computeParameterIfAbsent(String name, Supplier<Object> supplier) {
        return getParameterOpt(name).orElseGet(() -> {
            Object value = supplier.get();
            setParameter(name, value);
            return value;
        });
    }

    /**
     * 根据名称获取指定类型的参数
     *
     * @param name                   参数名称
     * @param requiredParameterClass 参数的类型
     *
     * @return 参数对象，如果不存在则返回 {@code Optional.empty()}
     */
    <T> Optional<T> getParameterOpt(String name, Class<T> requiredParameterClass);

    /**
     * 根据名称获取指定类型的参数
     *
     * @param name                   参数名称
     * @param requiredParameterClass 参数的类型
     *
     * @return 参数对象，如果不存在则返回 {@code null}
     */
    @Nullable
    default <T> T getParameter(String name, Class<T> requiredParameterClass) {
        return getParameterOpt(name, requiredParameterClass).orElse(null);
    }

    /**
     * 根据名称获取指定类型的参数，不存在则创建并放入
     *
     * @param name                   参数名称
     * @param requiredParameterClass 参数的类型
     * @param supplier               如果不存在则创建的函数
     *
     * @return 参数对象
     */
    default <T> T computeParameterIfAbsent(String name, Class<T> requiredParameterClass, Supplier<T> supplier) {
        return getParameterOpt(name, requiredParameterClass).orElseGet(() -> {
            T value = supplier.get();
            setParameter(name, value);
            return value;
        });
    }

    /**
     * 获取指定类型的参数
     *
     * @param requiredParameterClass 参数的类型
     * @param <T>                    需要的参数类型
     *
     * @return 指定类型的参数列表
     */
    <T> List<T> getParameters(Class<T> requiredParameterClass);

    /**
     * 获取处理前的响应对象
     */
    @Nullable
    Object getInitialResponse();

    /**
     * 获取处理后的响应对象
     */
    @Nullable
    Object getResponse();

    /**
     * 设置处理后的响应对象
     * @param response 响应对象
     */
    void setResponse(@Nullable Object response);

    /**
     * 获取处理结果
     */
    @Nullable
    Object getResult();

    /**
     * 设置处理结果，但是不意味着处理结束，结束处理流程需要调用{@link #complete()}
     *
     * @param result 处理结果
     */
    void setResult(@Nullable Object result);

    /**
     * 是否已完成处理
     */
    boolean isCompleted();

    /**
     * 标记完成处理，终止响应处理流程
     * <p>实现类必须完成标记为已处理的逻辑，即使{@link #isCompleted}返回{@code true}
     */
    void complete();

    /**
     * 标记完成处理，终止响应处理流程，并且设置处理结果
     *
     * @param result 处理结果
     */
    default void complete(@Nullable Object result) {
        setResult(result);
        complete();
    }
}
